import tkinter as tk
from tkinter import messagebox
import random
import time
import json

class Minesweeper:
    def __init__(self, master):
        self.master = master
        self.master.title("扫雷")
        self.master.configure(bg='#f0f0f0')
        
        # 颜色主题
        self.colors = {
            1: '#1976D2',  # 蓝色
            2: '#388E3C',  # 绿色
            3: '#D32F2F',  # 红色
            4: '#7B1FA2',  # 紫色
            5: '#FF8F00',  # 橙色
            6: '#0097A7',  # 青色
            7: '#424242',  # 深灰
            8: '#9E9E9E'   # 浅灰
        }
        
        # 难度设置
        self.difficulty_settings = {
            '初级': {'size': 9, 'mines': 10},
            '中级': {'size': 16, 'mines': 40},
            '高级': {'size': 22, 'mines': 99}
        }
        self.current_difficulty = '初级'
        
        # 主题设置
        self.themes = {
            '经典主题': {
                'bg': '#f0f0f0',
                'button_bg': '#e0e0e0',
                'button_hover': '#d0d0d0',
                'revealed_bg': '#f5f5f5',
                'mine_bg': '#ffcdd2',
                'text_color': '#333333',
                'border_color': '#bdbdbd'
            },
            '暗色主题': {
                'bg': '#424242',
                'button_bg': '#616161',
                'button_hover': '#757575',
                'revealed_bg': '#484848',
                'mine_bg': '#b71c1c',
                'text_color': '#ffffff',
                'border_color': '#757575'
            },
            '现代主题': {
                'bg': '#ffffff',
                'button_bg': '#f5f5f5',
                'button_hover': '#e3f2fd',
                'revealed_bg': '#bbdefb',
                'mine_bg': '#ef9a9a',
                'text_color': '#2196f3',
                'border_color': '#90caf9'
            }
        }
        self.current_theme = '经典主题'
        
        # 游戏参数
        self.grid_size = self.difficulty_settings[self.current_difficulty]['size']
        self.mine_count = self.difficulty_settings[self.current_difficulty]['mines']
        self.buttons = []
        self.mines = set()
        self.flags = set()
        self.clicked = set()
        self.first_click = True
        self.game_started = False
        self.start_time = None
        self.timer_running = False
        
        # 加载最高分
        self.high_scores = self.load_high_scores()
        
        # 创建菜单栏
        self.create_menu()
        
        # 创建主框架
        self.main_frame = tk.Frame(self.master, bg=self.themes[self.current_theme]['bg'])
        self.main_frame.pack(expand=True, padx=20, pady=20)
        
        # 创建标题
        self.title_label = tk.Label(
            self.main_frame,
            text="扫雷",
            font=('Microsoft YaHei UI', 24, 'bold'),
            bg=self.themes[self.current_theme]['bg'],
            fg=self.themes[self.current_theme]['text_color'],
            pady=15
        )
        self.title_label.pack()
        
        # 创建状态框架
        self.status_frame = tk.Frame(
            self.main_frame,
            bg=self.themes[self.current_theme]['bg'],
            relief=tk.GROOVE,
            borderwidth=2
        )
        self.status_frame.pack(pady=10, padx=20, fill=tk.X)
        
        # 创建计时器标签
        self.timer_label = tk.Label(
            self.status_frame,
            text="时间: 0",
            font=('Microsoft YaHei UI', 12, 'bold'),
            bg=self.themes[self.current_theme]['bg'],
            fg=self.themes[self.current_theme]['text_color'],
            width=10,
            pady=5
        )
        self.timer_label.pack(side=tk.LEFT, padx=20)
        
        # 创建地雷计数器
        self.mine_counter = tk.Label(
            self.status_frame,
            text=f"剩余地雷: {self.mine_count}",
            font=('Microsoft YaHei UI', 12, 'bold'),
            bg=self.themes[self.current_theme]['bg'],
            fg=self.themes[self.current_theme]['text_color'],
            width=12,
            pady=5
        )
        self.mine_counter.pack(side=tk.LEFT, padx=20)
        
        # 创建最高分标签
        self.high_score_label = tk.Label(
            self.status_frame,
            text=self.get_high_score_text(),
            font=('Microsoft YaHei UI', 12, 'bold'),
            bg=self.themes[self.current_theme]['bg'],
            fg=self.themes[self.current_theme]['text_color'],
            pady=5
        )
        self.high_score_label.pack(side=tk.LEFT, padx=20)
        
        # 创建游戏网格框架
        self.game_frame = tk.Frame(self.main_frame, bg=self.themes[self.current_theme]['bg'])
        self.game_frame.pack(pady=10)
        
        # 创建游戏网格
        self.create_grid()
        
        # 初始化游戏
        self.init_game()

    def create_menu(self):
        menubar = tk.Menu(self.master)
        self.master.config(menu=menubar)
        
        # 游戏菜单
        game_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="游戏", menu=game_menu)
        game_menu.add_command(label="新游戏", command=self.reset_game, accelerator="F2")
        game_menu.add_separator()
        game_menu.add_command(label="退出", command=self.master.quit, accelerator="Alt+F4")
        
        # 难度菜单
        difficulty_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="难度", menu=difficulty_menu)
        self.difficulty_var = tk.StringVar(value=self.current_difficulty)
        for diff in ['初级', '中级', '高级']:
            difficulty_menu.add_radiobutton(
                label=diff,
                variable=self.difficulty_var,
                value=diff,
                command=lambda d=diff: self.change_difficulty(d)
            )
        
        # 主题菜单
        theme_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="主题", menu=theme_menu)
        self.theme_var = tk.StringVar(value=self.current_theme)
        for theme in self.themes.keys():
            theme_menu.add_radiobutton(
                label=theme,
                variable=self.theme_var,
                value=theme,
                command=lambda t=theme: self.change_theme(t)
            )
        
        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="游戏说明", command=self.show_help)
        help_menu.add_command(label="关于", command=self.show_about)
        
        # 绑定快捷键
        self.master.bind('<F2>', lambda e: self.reset_game())

    def show_help(self):
        help_text = """
游戏说明：
1. 左键点击：揭开方块
2. 右键点击：标记地雷
3. 双击数字：当周围旗子数量等于数字时，自动揭开周围未标记的方块
4. 游戏目标：标记出所有地雷，避免踩到地雷

快捷键：
F2：开始新游戏
Alt+F4：退出游戏
"""
        messagebox.showinfo("游戏说明", help_text)

    def show_about(self):
        about_text = """
扫雷 v1.0
一个经典的扫雷游戏实现
作者：ljh
"""
        messagebox.showinfo("关于", about_text)

    def change_theme(self, theme):
        self.current_theme = theme
        theme_colors = self.themes[theme]
        
        # 更新主窗口
        self.master.configure(bg=theme_colors['bg'])
        self.main_frame.configure(bg=theme_colors['bg'])
        self.status_frame.configure(bg=theme_colors['bg'])
        self.game_frame.configure(bg=theme_colors['bg'])
        
        # 更新标签
        for label in [self.title_label, self.timer_label, self.mine_counter, self.high_score_label]:
            label.configure(
                bg=theme_colors['bg'],
                fg=theme_colors['text_color']
            )
        
        # 更新按钮
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                button = self.buttons[i][j]
                if button['state'] != 'disabled':
                    button.configure(bg=theme_colors['button_bg'])
                else:
                    button.configure(bg=theme_colors['revealed_bg'])

    def change_difficulty(self, difficulty):
        self.current_difficulty = difficulty
        self.grid_size = self.difficulty_settings[difficulty]['size']
        self.mine_count = self.difficulty_settings[difficulty]['mines']
        
        # 清除旧的网格
        for widget in self.game_frame.winfo_children():
            widget.destroy()
        
        self.buttons = []
        self.create_grid()
        self.reset_game()
        self.high_score_label.config(text=self.get_high_score_text())

    # 其他方法保持不变...
    def load_high_scores(self):
        try:
            with open('high_scores.json', 'r') as f:
                return json.load(f)
        except:
            return {'初级': 999, '中级': 999, '高级': 999}

    def save_high_scores(self):
        with open('high_scores.json', 'w') as f:
            json.dump(self.high_scores, f)

    def get_high_score_text(self):
        score = self.high_scores[self.current_difficulty]
        return f"最好成绩: {score if score != 999 else '无'}"

    def update_timer(self):
        if self.game_started and self.timer_running:
            elapsed_time = int(time.time() - self.start_time)
            self.timer_label.config(text=f"时间: {elapsed_time}")
            self.master.after(1000, self.update_timer)

    def create_grid(self):
        for i in range(self.grid_size):
            row = []
            for j in range(self.grid_size):
                button = tk.Button(
                    self.game_frame,
                    width=2,
                    height=1,
                    font=('Microsoft YaHei UI', 10, 'bold'),
                    relief=tk.RAISED,
                    bg=self.themes[self.current_theme]['button_bg'],
                    borderwidth=1,
                    highlightthickness=1,
                    highlightbackground=self.themes[self.current_theme]['border_color']
                )
                button.grid(row=i, column=j, padx=2, pady=2)
                button.bind('<Button-1>', lambda e, x=i, y=j: self.click(x, y))
                button.bind('<Button-3>', lambda e, x=i, y=j: self.toggle_flag(x, y))
                button.bind('<Double-Button-1>', lambda e, x=i, y=j: self.double_click(x, y))
                button.bind('<Enter>', lambda e, b=button: self.on_hover_enter(b))
                button.bind('<Leave>', lambda e, b=button: self.on_hover_leave(b))
                row.append(button)
            self.buttons.append(row)

    def init_game(self):
        self.mines.clear()
        self.flags.clear()
        self.clicked.clear()
        self.first_click = True
        self.game_started = False
        self.timer_running = False
        self.timer_label.config(text="时间: 0")
        self.mine_counter.config(text=f"剩余地雷: {self.mine_count}")

    def place_mines(self, first_x, first_y):
        safe_cells = {(first_x, first_y)}
        for nx, ny in self.get_neighbors(first_x, first_y):
            safe_cells.add((nx, ny))
        
        while len(self.mines) < self.mine_count:
            x = random.randint(0, self.grid_size-1)
            y = random.randint(0, self.grid_size-1)
            if (x, y) not in safe_cells and (x, y) not in self.mines:
                self.mines.add((x, y))

    def click(self, x, y):
        if (x, y) in self.flags or (x, y) in self.clicked:
            return

        if self.first_click:
            self.first_click = False
            self.game_started = True
            self.start_time = time.time()
            self.timer_running = True
            self.update_timer()
            self.place_mines(x, y)

        if (x, y) in self.mines:
            self.timer_running = False
            self.reveal_all()
            messagebox.showinfo("游戏结束", "很遗憾，你踩到地雷了！")
            self.reset_game()
            return

        self.reveal(x, y)
        
        if len(self.clicked) == self.grid_size * self.grid_size - len(self.mines):
            self.timer_running = False
            elapsed_time = int(time.time() - self.start_time)
            
            if elapsed_time < self.high_scores[self.current_difficulty]:
                self.high_scores[self.current_difficulty] = elapsed_time
                self.save_high_scores()
                self.high_score_label.config(text=self.get_high_score_text())
                messagebox.showinfo("恭喜", f"新纪录！用时：{elapsed_time}秒")
            else:
                messagebox.showinfo("恭喜", f"你赢了！用时：{elapsed_time}秒")
            
            self.reset_game()

    def reveal(self, x, y):
        if (x, y) in self.clicked or (x, y) in self.flags:
            return
            
        self.clicked.add((x, y))
        count = self.count_adjacent_mines(x, y)
        button = self.buttons[x][y]
        
        if count == 0:
            button.config(
                text="",
                relief=tk.FLAT,
                bg=self.themes[self.current_theme]['revealed_bg'],
                state='disabled'
            )
            for nx, ny in self.get_neighbors(x, y):
                self.reveal(nx, ny)
        else:
            button.config(
                text=str(count),
                relief=tk.FLAT,
                bg=self.themes[self.current_theme]['revealed_bg'],
                fg=self.colors.get(count, self.themes[self.current_theme]['text_color']),
                state='disabled'
            )

    def toggle_flag(self, x, y):
        if (x, y) in self.clicked:
            return
            
        button = self.buttons[x][y]
        if (x, y) in self.flags:
            self.flags.remove((x, y))
            button.config(
                text="",
                bg=self.themes[self.current_theme]['button_bg']
            )
            self.mine_counter.config(text=f"剩余地雷: {self.mine_count - len(self.flags)}")
        else:
            self.flags.add((x, y))
            button.config(text="🚩", fg='#D32F2F')
            self.mine_counter.config(text=f"剩余地雷: {self.mine_count - len(self.flags)}")

    def reveal_all(self):
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                button = self.buttons[i][j]
                if (i, j) in self.mines:
                    button.config(
                        text="💣",
                        bg=self.themes[self.current_theme]['mine_bg'],
                        fg='#b71c1c'
                    )
                else:
                    count = self.count_adjacent_mines(i, j)
                    if count > 0:
                        button.config(
                            text=str(count),
                            bg=self.themes[self.current_theme]['revealed_bg'],
                            fg=self.colors.get(count, self.themes[self.current_theme]['text_color']),
                            relief=tk.FLAT
                        )

    def reset_game(self):
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                self.buttons[i][j].config(
                    text="",
                    relief=tk.FLAT,
                    bg=self.themes[self.current_theme]['button_bg'],
                    state='normal'
                )
        self.init_game()

    def get_neighbors(self, x, y):
        neighbors = []
        for i in range(max(0, x-1), min(self.grid_size, x+2)):
            for j in range(max(0, y-1), min(self.grid_size, y+2)):
                if (i, j) != (x, y):
                    neighbors.append((i, j))
        return neighbors

    def count_adjacent_mines(self, x, y):
        count = 0
        for nx, ny in self.get_neighbors(x, y):
            if (nx, ny) in self.mines:
                count += 1
        return count

    def on_hover_enter(self, button):
        if button['state'] != 'disabled':
            button.configure(bg=self.themes[self.current_theme]['button_hover'])

    def on_hover_leave(self, button):
        if button['state'] != 'disabled':
            button.configure(bg=self.themes[self.current_theme]['button_bg'])

    def double_click(self, x, y):
        if not self.game_started or (x, y) not in self.clicked:
            return
            
        button = self.buttons[x][y]
        if button['state'] == 'disabled' and button['text'].isdigit():
            mine_count = int(button['text'])
            flag_count = sum(1 for nx, ny in self.get_neighbors(x, y) if (nx, ny) in self.flags)
            
            if flag_count == mine_count:
                for nx, ny in self.get_neighbors(x, y):
                    if (nx, ny) not in self.flags and (nx, ny) not in self.clicked:
                        self.click(nx, ny)

if __name__ == "__main__":
    root = tk.Tk()
    root.configure(bg='#f0f0f0')
    game = Minesweeper(root)
    root.mainloop()  